iT邦幫忙

2023 iThome 鐵人賽

DAY 21
0

Table of Contents

  • offset
    • offsetParent
    • offsetLeft/offsetTop
    • offsetWidth/offsetHeight
  • client
    • clientTop/clientLeft
    • clientWidth/clientHeight
  • scroll
    • scrollLeft/scrollTop
  • getBoundingClientRect()
  • References

今天先來認識元素的尺寸怎麽抓座標,對今天只是想找元素的尺寸與座標而已。
如果有寫過Javascript30的朋友,應該知道裡面有幾天都在抓座標取特定的尺寸,而我感覺就是跟著看、跟著讀、跟著用,但實際上看了文件後還是一片混亂,所以先把範圍鎖小在今天的元素。

offset

offset的特徵是計算偏離祖先元素的位置。

offsetParent

會被決定為祖先元素的優先順序如下:

  1. 祖先元素有使用非靜態的positionabsoluterelativefixedsticky
  2. 祖先元素是靜態的<table><td><th>
  3. 如果沒有以上的定位,祖先元素是<body>

示範祖父元素中有定位:

<div class='outer'>
  <div class='inner'>
      <p>inner</p>
  <div>
</div>
.outer{
  display:flex;
  align-content:center;
  position:absolute;
  width:200px;
  height:200px;
  padding:10px;
  background-color:gray;
}

.inner{
  width:50px;
  height:50px;
  padding:10px;
  margin:auto;
  border:5px solid;
  background-color:orange;
}
const inner = document.querySelector('.inner')
console.log(inner.offsetParent)//div.outer

示範使用到<table>HTML結構:

<table>
  <tr>
    <td>
      <div class='outer'>
        <div class='inner'><p>inner</p></div>
      </div>
    </td>
  </tr>
</table>
const inner = document.querySelector('.inner')
console.log(inner.offsetParent)//td

在某些狀態下,元素如果符合條件,那offsetParent會是null

  1. 被指定的元素是<body><HTML>
  2. 被指定的元素有設定positionfixed
  3. 被指定的的元素設定display:none或者根本不在document上面。

offsetLeft/offsetTop

找到祖父元素後,就可以使用這組方法找到相對於祖父元素偏離的距離,比方說呈現在畫面上有兩個方塊。

<div class='outer'>outer
  <div class='inner'>
      <p>inner</p>
  </div>
</div>
const inner = document.querySelector('.inner')
console.log(`X為${inner.offsetLeft},Y為${inner.offsetTop}`)
//X為43,Y為10

offsetWidth/offsetHeight

offset計算的是元素的content+padding+scroll+border
注意,不是設定的width,是元素本身的內容大小content
現在我把上面的橘色區塊加上很多文字,改變CSS樣式,讓他能夠被捲軸捲動。

<div class='outer'>outer
    <div class='inner'>
        <p>
            innerinnerinnerinnerinnerinnerinnerinner
            innerinnerinnerinnerinnerinnerinnerinnerinnerinnerinner
            innerinnerinnerinnerinnerinnerinnerinnerinnerinnerinner
        </p>
    <div>
</div>

現在的模樣長的像下面:

(這是圖片)

.outer{
  display:flex;
  align-content:center;
  width:200px;
  height:200px;
  padding:10px;
  background-color:gray;
}

.inner{
  width:50px;
  height:50px;
  padding:10px;
  border:5px solid;
  background-color:orange;
  overflow: auto;
  word-break:break-all;
}
const inner = document.querySelector('.inner')
console.log(`寬為${inner.offsetWidth},高為${inner.offsetHeight}`)//寬為80,高為80

剛剛有提到寬高是content+padding+scroll+border,在box model顯示innercontent是38,所以38+10 * 2+5 * 2加上捲軸寬就是這個元素的offsetWidth了。至於高度不受捲軸影響,所以是50+10 * 2+5 * 2。

client

client比較像計算元素本身一些細節。

clientTop/clientLeft

clientTopLeft這段距離是元素的border加上捲軸(如果是從文字由右到左,並且文字溢出導致多出捲軸)的寬度。

.inner{
  width:50px;
  height:50px;
  padding:10px;
  border:5px solid;
  background-color:orange;
  overflow: auto;
  word-break:break-all;
}
const inner = document.querySelector('.inner')
console.log(`X為${inner.clientLeft},Y為${inner.clientTop}`)
//X為5,Y為5

clientWidth/clientHeight

clientWidthclientHeight的寬高是元素的content加上padding。

const inner = document.querySelector('.inner')
console.log(`寬為${inner.clientWidth},高為${inner.clientHeight}`)
//寬為58,高為58

其中padding為10,元素本身內容的寬度為38,所以加起來就是58。

scroll

scroll是把超出的文字改成捲動之後,尺寸是可見內容加上被隱藏的部份。

比方說以這張圖來說,第二行下面還有很多的空間裝著文字,這些就是scroll的範圍。

scrollLeft/scrollTop

left跟top都是滾動的距離。

const inner = document.querySelector('.inner')
//以事件測試輸出捲動距離
inner.addEventListener('scroll',()=>{
  console.log(inner.scrollTop)
})

scrollWidth/Height

scrollWidthscrollHeight計算隱藏的空間大小。

const inner = document.querySelector('.inner')
console.log(inner.scrollWidth)//240

getBoundingClientRect()

Element.getBoundingClientRect()會回傳一個DOMRect物件,這個物件會顯示相對viewport左上角的一些距離,分別有一些屬性可以使用。

bottom是從視口到元素底部的距離,而right則是視口到元素右邊邊框的距離,所以右邊跟下面如果有paddingborder這些看得到的空間就會加上去,但margin就沒有。

width跟height是元素本身加上paddingborder的距離,但如果有先設定box-sizingborder-box,那麽寬高就等同於widthheight
top跟y、left跟x基本上這一組數值會一樣。

這些數值會依照視口的捲動改變。

如上圖往下拉之後,y會因為空間變少的關係變少或者是負的,而bottom也是一樣。

References

Element size and scrolling
Element: getBoundingClientRect() method


上一篇
〈Day20〉處理DOM的屬性
下一篇
〈Day22〉事件與事件傳遞
系列文
廚藝不精也可以,給自己做一份Javascript小火鍋30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言